import os
import random
import re
import time
import uuid
from enum import Enum
from hashlib import md5, sha256

import requests

from .config import Settings
from .log import logger

os.environ['NO_PROXY'] = 'api.fanyi.baidu.com, fanyi-api.baidu.com, openapi.youdao.com'


class Language(Enum):
    zh_cn = 0
    en = 1
    ja = 2

    @staticmethod
    def detect(string: str, l1, l2):
        """
        语言类型检测，通过 Unicode 属性和正则表达式判断相应字符的数量
        :param string: 待检测的字符串
        :param l1: 期待检测到的语言 1（枚举成员）
        :param l2: 期待检测到的语言 2（枚举成员）
        :return: 检测结果，返回枚举成员
        """
        chinese_pattern = r'[\u4e00-\u9fa5]+'
        english_pattern = r'[A-Za-z]+'
        japanese_pattern = r'[\u3040-\u309F\u30A0-\u30FF\u31F0-\u31FF]'

        cmp_list = []

        if l1 == Language.zh_cn or l2 == Language.zh_cn:
            chinese_count = re.findall(chinese_pattern, string)
            zh_cn = Language.zh_cn, chinese_count
            cmp_list.append(zh_cn)

        if l1 == Language.en or l2 == Language.en:
            english_count = re.findall(english_pattern, string)
            en = Language.en, english_count
            cmp_list.append(en)

        if l1 == Language.ja or l2 == Language.ja:
            japanese_count = re.findall(japanese_pattern, string)
            ja = Language.ja, japanese_count
            cmp_list.append(ja)

        cmp_list.sort(key=lambda x: x[1], reverse=True)

        return cmp_list[0][0]


class Baidu(object):
    def __init__(self):
        self.trans_url = 'http://api.fanyi.baidu.com/api/trans/vip/translate'
        self.lng_id_url = 'https://fanyi-api.baidu.com/api/trans/vip/language'
        self.headers = {'Content-Type': 'application/x-www-form-urlencoded'}

        self.settings = Settings()
        self.app_id = self.settings.baidu_app_id
        self.secret_key = self.settings.baidu_secret_key

    @staticmethod
    def __make_md5(value):
        return md5(value.encode('utf-8')).hexdigest()

    def language_identify(self, text) -> str:
        salt = random.randint(32768, 65536)
        sign = self.__make_md5(self.app_id + text + str(salt) + self.secret_key)

        payload = {'appid': self.app_id, 'q': text, 'salt': salt, 'sign': sign}
        resp = requests.post(self.lng_id_url, params=payload, headers=self.headers).json()
        result = ''

        try:
            result = resp['data']['src']
        except KeyError:
            logger.exception(resp)
        finally:
            return result

    def translate(self, text, from_lang, to_lang):
        # Generate salt and sign
        salt = random.randint(32768, 65536)
        try:
            sign = self.__make_md5(self.app_id + text + str(salt) + self.secret_key)
        except TypeError:
            logger.exception(f'Baidu appID or secret key is not initialized!'
                             f' app_id = {self.app_id}, secret_key = {self.secret_key}')
            return ''

        # Build request
        payload = {'appid': self.app_id, 'q': text, 'from': from_lang, 'to': to_lang, 'salt': salt, 'sign': sign}

        # Send request
        resp = requests.post(self.trans_url, params=payload, headers=self.headers).json()
        result = ''

        try:
            result = '\n'.join([i['dst'] for i in resp['trans_result']])
        except KeyError:
            logger.exception(resp)
        finally:
            return result


class Youdao(object):

    def __init__(self):
        self.trans_url = 'https://openapi.youdao.com/api'
        self.headers = {'Content-Type': 'application/x-www-form-urlencoded'}

        self.settings = Settings()
        self.app_id = self.settings.youdao_app_id
        self.secret_key = self.settings.youdao_secret_key

    @staticmethod
    def __truncate(q):
        if q is None:
            return None
        size = len(q)
        return q if size <= 20 else q[0:10] + str(size) + q[size - 10:size]

    @staticmethod
    def __encrypt(sign_str):
        hash_algorithm = sha256()
        hash_algorithm.update(sign_str.encode('utf-8'))
        return hash_algorithm.hexdigest()

    def translate(self, text, from_lang, to_lang, domain='general', reject_fallback='false'):
        data = {
            'from': from_lang,
            'to': to_lang,
            'signType': 'v3',
            'appKey': self.app_id,
            'q': text,
            'strict': 'false',  # 非严格按照 from 和 to 翻译
        }

        cur_time = str(int(time.time()))
        salt = str(uuid.uuid1())

        try:
            sign_str = self.app_id + self.__truncate(text) + salt + cur_time + self.secret_key
        except TypeError:
            logger.exception(f'Youdao appID or secret key is not initialized!'
                             f' app_id = {self.app_id}, secret_key = {self.secret_key}')
            return ''

        sign = self.__encrypt(sign_str)

        data['curtime'] = cur_time
        data['salt'] = salt
        data['sign'] = sign

        if domain != 'general':
            data['domain'] = domain
            if reject_fallback:
                data['rejectFallback'] = 'true'

        resp = requests.post(url=self.trans_url, data=data, headers=self.headers).json()
        result = ''

        try:
            result = '\n'.join([i for i in resp['translation']])
        except KeyError:
            logger.exception(resp)
        finally:
            return result
